<?php


namespace NanQi\Hope\Sync;


use Closure;
use Cron\CronExpression;
use NanQi\Hope\Base\BaseSync;
use NanQi\Hope\Constants\CacheSyncConstants;
use NanQi\Hope\Hope;

/**
 * 缓存一致性解决方案
 * Class CacheSync
 * @package NanQi\Hope\Sync
 */
class CacheSync extends BaseSync
{
    /**
     * 设置行为缓冲
     * @param string $prefix 类型前缀
     * @param $user_id
     * @param string $crontabRule
     * @throws \Exception
     */
    public function setActionBuffer(string $prefix, $user_id, string $crontabRule = '')
    {
        $redis = $this->getRedisBusiness();

        $cron = new CronExpression($this->getCrontabRule($crontabRule));
        $cacheKey = sprintf(CacheSyncConstants::SYNC_CACHE_KEY, $prefix,
            date('YmdHi', $cron->getNextRunDate()->getTimestamp()));

        $redis->sAdd($cacheKey, $user_id);
    }

    /**
     * 同步行为缓冲
     * @param string $prefix
     * @param Closure $func
     * @param string $crontabRule
     * @throws \Exception
     */
    public function syncActionBuffer(string $prefix, Closure $func, string $crontabRule = '')
    {
        $redis = $this->getRedisBusiness();

        $cacheKey = $this->getPreActionBufferCacheKey($prefix, $crontabRule);
        if (!$redis->exists($cacheKey)) {
            return;
        }

        //临时处理，应该分批弹出
//        $redis->eval("spop " . $cacheKey . ' ' . );
        $list = $redis->sMembers($cacheKey);
        $flg = $func->call($this, $list);
        if ($flg) {
            $redis->del($cacheKey);
        }
    }

    /**
     * 获取上一个要处理的行为缓冲Key值
     * @param string $prefix
     * @param string $crontabRule
     * @return string
     * @throws \Exception
     */
    public function getPreActionBufferCacheKey(string $prefix, string $crontabRule = "") : string
    {
        $cron = new CronExpression($this->getCrontabRule($crontabRule));
        $cacheKey = sprintf(CacheSyncConstants::SYNC_CACHE_KEY, $prefix,
            date('YmdHi', $cron->getPreviousRunDate('now', 0, true)->getTimestamp()));
        return $cacheKey;
    }

    private function getCrontabRule(string $crontabRule = '')
    {
        if ($crontabRule) {
            return $crontabRule;
        }

        $crontabRule = config('hope.cron-sync-buffer', '*/10 * * * *');
        if ($crontabRule) {
            return $crontabRule;
        }

        return "*/10 * * * *";
    }
}